/*
 * Copyright (c) 2020 hebeiyiliuba.com
 * All rights reserved.
 *
 */

package org.jeecg.modules.third.jg.report.freight.information.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.third.jg.report.freight.information.constant.MingnaReportConstant;
import org.jeecg.modules.third.jg.report.freight.information.constant.SxReportConstant;
import org.jeecg.modules.third.jg.report.freight.information.constant.enums.ReportDocTypeEnum;
import org.jeecg.modules.third.jg.report.freight.information.dto.AppInfoDTO;
import org.jeecg.modules.third.jg.report.freight.information.model.R;
import org.jeecg.modules.third.jg.report.freight.information.model.Root;
import org.jeecg.modules.third.jg.report.freight.information.util.sm.SM2Util;
import org.jeecg.modules.third.jg.report.freight.information.util.sm.SM4Util;
import org.jeecg.modules.wlhy.utils.HyCfgUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Description: 铭钠监管系统上报服务
 */
@Service
@Slf4j
public class MingnaReportPlatformService {

    @Resource
    private RedisUtil redisUtil;

    private String domainURL;

    private String username;

    private String password;

    private String publicKey;

    private String debugSystem;

    private String appId;

    private String appSecurity;

    private String appSenderCode;

    private String appDebugSystem;

    public AppInfoDTO getAppInfo() {
        return AppInfoDTO.builder()
                .appId(this.appId)
                .appSecurity(this.appSecurity)
                .enterpriseSenderCode(this.appSenderCode)
                .debugSystem(this.appDebugSystem)
                .build();
    }

    public void setReportInfo(String reportPlatformDomain,
                              String username,
                              String password,
                              String publickey,
                              String appId,
                              String appSecurity,
                              String appSenderCode,
                              String appDebugSystem) {
        //联调状态的App需要设置debugSystem
        if ("0".equals(appDebugSystem)) {
            appDebugSystem = "debugSystem";
        }

        this.domainURL = reportPlatformDomain;
        this.username = username;
        this.password = password;
        this.publicKey = publickey;
        this.debugSystem = "";
        this.appId = appId;
        this.appSecurity = appSecurity;
        this.appSenderCode = appSenderCode;
        this.appDebugSystem = appDebugSystem;
    }

    private String getLoginToken() throws Exception {

        if (!HyCfgUtil.isUsed("mingna_report")) {
            throw new JeecgBootException("铭钠上报服务暂未开启,请联系管理员。");
        }

        if (StrUtil.isEmpty(this.domainURL) || StrUtil.isEmpty(this.username) || StrUtil.isEmpty(this.password) || StrUtil.isEmpty(this.publicKey)) {
            throw new JeecgBootException("铭钠上报服务参数配置错误,请联系管理员。");
        }

        log.info("{} - {} - {} - {}", this.domainURL, this.username, this.password, this.publicKey);
        Object tokenObject = redisUtil.get(MingnaReportConstant.API_REPORT_TOKEN_KEY + "_" + this.username);
        if (tokenObject != null) {
            return tokenObject.toString();
        }

        String encryptPassword = SM2Util.encrypt(publicKey, this.password);
        String url = this.domainURL + MingnaReportConstant.AUTH_URL;

        Map<String, String> loginParam = new HashMap<>();
        loginParam.put("username", this.username);
        loginParam.put("password", encryptPassword);
        loginParam.put("mode", "debug");

        String authResult = HttpUtil.post(url, JSONUtil.toJsonStr(loginParam));
        log.info("铭钠监管上报获取Token回执 <- {}", authResult);

        Map<String, Object> loginResultMap = JSON.parseObject(authResult, Map.class);
        int code = (int) loginResultMap.get("code");
        if (0 != code) {
            throw new Exception("token获取异常," + loginResultMap.get("msg"));
        }

        redisUtil.set(MingnaReportConstant.API_REPORT_TOKEN_KEY + "_" + this.username, authResult, MingnaReportConstant.API_REPORT_TOKEN_KEY_EXPIRE);
        return authResult;
    }



    /**
     * 组装交换报文
     * @param reportDocTypeEnum 上报单据类型
     * @param jsonString 报文内容
     * @return
     */
    private Root messageAssembly(ReportDocTypeEnum reportDocTypeEnum ,String jsonString) throws Exception {

        if (!ReportDocTypeEnum.isValid(reportDocTypeEnum.getCode()) || StringUtils.isEmpty(jsonString)) {
            throw new JeecgBootException("上报单据类型异常");
        }

        //组装交换报文
        Root root = new Root();
        root.setMessageReferenceNumber(UUID.randomUUID().toString().replace("-", ""));
        root.setDocumentName(reportDocTypeEnum.getMsg());
        root.setDocumentVersionNumber("1.0");
        root.setSenderCode(this.username);
        root.setMessageSendingDateTime(DateUtils.dateToStringDateTime(new Date()));
        root.setIpcType(reportDocTypeEnum.getCode());
        //root.setRecipientCode("wlhymot");
        //root.setToken(token);
        //root.setUserName(this.username);
        String key = null;
        try {
            //String encrypt = null;
            //生成对称密钥
            //key = SM4Util.generateKey();
            //使用对称密钥加密业务报文
            //String encryptBase64 = SM4Util.encrypt_Ecb_Padding(key, jsonString);
            //使用sm2公用加密对称密钥
            String encrypt = SM2Util.encrypt(this.publicKey, jsonString);
            //root.setEncryptedCode(encrypt);
            root.setEncryptedContent(encrypt);
            return root;
        } catch (Exception e) {
            log.error("铭钠上报组装交换报文异常:{}" ,  e.getMessage());
        }

        return null;
    }

    /**
     * 发送上报
     * @param reportDocTypeEnum
     * @param jsonString
     */
    public String sendReport(ReportDocTypeEnum reportDocTypeEnum ,String jsonString) throws Exception {

        String loginPost = getLoginToken();
        if (StrUtil.isEmpty(loginPost)) {
            throw new JeecgBootException("监管平台token获取异常");
        }

        Map<String, Object> loginResultMap = JSON.parseObject(loginPost, Map.class);
        String token = (String) ((Map) loginResultMap.get("data")).get("token");

        Root exchangeModel = messageAssembly(reportDocTypeEnum, jsonString);
        if (exchangeModel != null) {
            //发送报文
            //如果配置了debugSystem，向联调环境发送请求
            String url = this.domainURL + MingnaReportConstant.SEND_URL;

            log.info("铭钠上报报文请求 -> {}, {}", exchangeModel.getMessageReferenceNumber(), jsonString);
            HttpResponse response = HttpRequest.post(url)
                    .header("Content-Type", "application/json; UTF-8")
                    .header("Authorization", token)
                    .body(JSONUtil.toJsonStr(exchangeModel))
                    .execute();

            String sendResult = response.body();
            log.info("铭钠上报报文回执 <- {}", sendResult);
            if (StrUtil.isNotEmpty(sendResult)) {
                return sendResult;
            }
        }

        return StrUtil.EMPTY;
    }


    /**
     * 上传文件
     */
    public String uploadFile(String filePath, String filetype) throws Exception {

        File file = new File(filePath);
        if (!file.exists()) {
            log.error(filetype + "文件不存在");
            return StrUtil.EMPTY;
        }

        String loginPost = getLoginToken();
        if (StrUtil.isEmpty(loginPost)) {
            throw new JeecgBootException("监管平台token获取异常");
        }

        Map<String, Object> loginResultMap = JSON.parseObject(loginPost, Map.class);
        String token = (String) ((Map) loginResultMap.get("data")).get("token");

        String url = this.domainURL + MingnaReportConstant.UPLOAD_URL;

        log.info("铭钠上报文件请求 -> {}, {}", filetype, filePath);
        HttpResponse response = HttpRequest.post(url)
                .header("Content-Type", "multipart/form-data;")
                .header("Authorization", token)
                .form("file", file)
                .execute();

        String sendResult = response.body();
        log.info("铭钠上报报文回执 <- {}", sendResult);
        if (StrUtil.isNotEmpty(sendResult)) {
            //{
            //    "code": 0,
            //    "msg": null,
            //    "data": "1b4a169c412f4ce487d45a851647553f.png",
            //    "ok": true
            //}

            JSONObject jsonObject = JSONUtil.parseObj(sendResult);
            return jsonObject.getStr("data");
        }

        return StrUtil.EMPTY;
    }
}
